﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;

[System.Serializable]
public class ResVersion
{
    public string resVersion = "0.0.0";
    public Dictionary<string, ResVersionItem> bundleDic = new Dictionary<string, ResVersionItem>();
}

[System.Serializable]
public class ResVersionItem
{
    public string guid;
    public string bundlePath;
    public long size;

    public ResVersionItem(string guid, string bundlePath, long size)
    {
        this.guid = guid;
        this.bundlePath = bundlePath;
        this.size = size;
    }
}

public class BundleUpdateManager : SingletonManager<BundleUpdateManager>
{
    [System.Serializable]
    class AppVersionInfo
    {
        public string AppVersion = "0.0.0";
        public List<string> ResServerUrls = new List<string>();
    }

    enum DOWN_STATE
    {
        UnDown = 0,
        DownLoad = 1,
        Finish = 2,
    }


    public string LocalAppVersion
    {
        get
        {
            if (versionInfo == null || string.IsNullOrEmpty(versionInfo.AppVersion))
            {
                return "0.0.0";
            }
            else
            {
                return versionInfo.AppVersion;
            }
        }
    }
    public string LocalResVersion = "0.0.0";
    public string ServerAppVersion = "0.0.0";
    public string ServerResVersion
    {
        get
        {
            if (resVersion == null || string.IsNullOrEmpty(resVersion.resVersion))
            {
                return "0.0.0";
            }
            else
            {
                return resVersion.resVersion;
            }
        }
    }

    private AppVersionInfo versionInfo;
    private int versionInfoUrlIndex = 0;

    public ResVersion resVersion;

    public const int MAX_DOWNFILE_COUNT = 5;

    Dictionary<string, DOWN_STATE> DownFileDic = new Dictionary<string, DOWN_STATE>();

    IEnumerator DownFile(string fileName, Action<UnityWebRequest> successCallBack, Action<UnityWebRequest> errorCallBack)
    {
        string url = versionInfo.ResServerUrls[versionInfoUrlIndex] + fileName;
        Debug.Log("连接" + url);
        UnityWebRequest request = UnityWebRequest.Get(url);

        yield return request.SendWebRequest();

        if (!string.IsNullOrEmpty(request.error))
        {
            Debug.LogError(url + "连接失败" + " ErrorCode:" + request.error);
            if (errorCallBack != null)
            {
                errorCallBack(request);
            }
        }
        else
        {
            byte[] results = request.downloadHandler.data;
            FileStream fileStream = File.Create(PathDefine.PERSISTENT_DATA + fileName);
            fileStream.Write(results, 0, results.Length);
            fileStream.Flush();
            fileStream.Close();

            if (successCallBack != null)
            {
                successCallBack(request);
            }
        }
    }

    private bool LoadConfig()
    {
        string localResVersion = PathDefine.RES_VERSION;
        if (File.Exists(localResVersion))
        {
            string[] lines = File.ReadAllLines(localResVersion);
            if (lines != null && lines.Length > 0)
            {
                LocalResVersion = lines[0].Trim().Split(' ')[1];
            }
        }



        TextAsset versionInfoJson = Resources.Load("server") as TextAsset;
        string json = versionInfoJson.text;
        versionInfo = JsonUtility.FromJson<AppVersionInfo>(json);

        if (versionInfo == null)
        {
            Debug.LogError("没有找到Resources/server.txt的配置");
            return false;
        }

        return true;
    }

    public void Start()
    {
        if (!LoadConfig())
        {
            return;
        }

        GameStart.Instance.StartCoroutine(DownFile("ResVersion.txt", GetServerSuccess, GetServerError));
    }

    public void Update()
    {

    }

    public void OnDestroy()
    {
    }

    private void GetServerError(UnityWebRequest request)
    {
        versionInfoUrlIndex++;
        if (versionInfoUrlIndex >= versionInfo.ResServerUrls.Count)
        {
            Debug.LogError("连接资源服务器失败");
            return;
        }

        GameStart.Instance.StartCoroutine(DownFile("ResVersion.txt", GetServerSuccess, GetServerError));

    }

    private void GetServerSuccess(UnityWebRequest request)
    {
        resVersion = GetResVersion(request.downloadHandler.text);
        CheckAndUpdate();
    }

    private void CheckAndUpdate()
    {
        DirectoryInfo di = new DirectoryInfo(PathDefine.PERSISTENT_DATA);

        Dictionary<string, long> localFileDic = new Dictionary<string, long>(); 
        foreach (FileInfo fi in di.GetFiles())
        {
            if (fi.Name == "ResVersion.txt")
            {
                continue;
            }

            localFileDic.Add(fi.Name, fi.Length);
        }

        //需要下载的文件
        Dictionary<string, DOWN_STATE> DownList = new Dictionary<string, DOWN_STATE>();
        //需要保留的文件
        Dictionary<string, long> RemainDic = new Dictionary<string, long>();
        foreach(var it in resVersion.bundleDic)
        {
            if (localFileDic.ContainsKey(it.Value.guid) && localFileDic[it.Value.guid] == it.Value.size)
            {
                string bundlePath = it.Value.bundlePath;
                if (bundlePath.Contains(":"))
                {
                    string v = bundlePath.Split(':')[1];
                    if (v != LocalResVersion)
                    {
                        DownList.Add(it.Value.guid, DOWN_STATE.UnDown);
                        continue;
                    }
                }
                RemainDic.Add(it.Value.guid, it.Value.size);
                continue;
            }
            DownList.Add(it.Value.guid, DOWN_STATE.UnDown);

        }

        //需要删除的文件
        List<string> DelList = new List<string>();
        foreach (FileInfo fi in di.GetFiles())
        {
            if (fi.Name == "ResVersion.txt")
            {
                continue;
            }

            if (DownList.ContainsKey(fi.Name))
            {
                continue;
            }

            if (RemainDic.ContainsKey(fi.Name))
            {
                continue;
            }

            DelList.Add(fi.Name);
        }

        //删除文件
        for (int i = 0; i < DelList.Count; i++)
        {
            File.Delete(PathDefine.PERSISTENT_DATA + DelList[i]);
        }

        //下载文件
        DownFileDic = DownList;
        DownFromServer();
    }

    private void DownFromServer()
    {
        if (DownFileDic.Count == 0)
        {
            UpdateSuccess();
        }
        else
        {
            List<string> temp = new List<string>();
            foreach (var it in DownFileDic)
            {
                temp.Add(it.Key) ;
                GameStart.Instance.StartCoroutine(DownFile(it.Key, DownSuccess, null));
                if (temp.Count >= MAX_DOWNFILE_COUNT)
                {
                    break;
                }
            }

            foreach (var it in temp)
            {
                DownFileDic[it] = DOWN_STATE.DownLoad;
            }
        }
    }

    private void DownSuccess(UnityWebRequest request)
    {
        string fileName = Path.GetFileName(request.url);
        DownFileDic[fileName] = DOWN_STATE.Finish;
        string nextName = null;
        foreach (var it in DownFileDic)
        {
            if (it.Value == DOWN_STATE.UnDown)
            {
                nextName = it.Key;
                GameStart.Instance.StartCoroutine(DownFile(it.Key, DownSuccess, null));
                break;
            }

            if (it.Value == DOWN_STATE.DownLoad)
            {
                return;
            }
        }

        if (!string.IsNullOrEmpty(nextName))
        {
            DownFileDic[nextName] = DOWN_STATE.DownLoad;
            return;
        }

        UpdateSuccess();
    }

    private void UpdateSuccess()
    {
        Debug.Log("UpdateSuccess");
        ResManager.Instance.Start();
        LuaManager.Instance.Start();
    }

    public static ResVersion GetResVersion(string text)
    {
        string[] s2 = text.Split('\n');

        ResVersion resVersion = new ResVersion();
        resVersion.resVersion = s2[0].Trim().Split(' ')[1];

        for (int i = 1; i < s2.Length; i++)
        {
            string line = s2[i].Trim();
            if (string.IsNullOrEmpty(line))
            {
                continue;
            }
            string[] temp = line.Split(' ');
            string bundleName = temp[0];
            string guid = temp[1];
            long size = Convert.ToInt64(temp[2]);
            ResVersionItem item = new ResVersionItem(guid, bundleName, size);
            resVersion.bundleDic.Add(bundleName, item);
        }


        return resVersion;
    }
}